//
//  DataSecurity.m
//  TestDataSecurity
//
//  Created by I三生有幸I on 16/4/14.
//  Copyright © 2016年 盛辰. All rights reserved.
//

#import "DataSecurity.h"

@implementation DataSecurity
#pragma mark --- 单例 ---
+ (DataSecurity *)shareInstance
{
    // 线程安全下的单例
    static DataSecurity *dataSecurity = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        dataSecurity = [[DataSecurity alloc]init];
    });
    return dataSecurity;
}

/**********
 
 以下是对加密/解密操作的方法
 
 **********/

#pragma mark --- MD5对字符串的加密 ---
// 使用方法 传入想要加密的字符串 返回该字符串进行MD5加密之后的字符串
- (NSString *)MD5WithString:(NSString *)string
{
    // 1.对MD5的加密 必须输对C语言字符串 所以要先将OC字符串 转化成C语言字符串
    const char *strUTF = string.UTF8String;
    
    // 2.创建字符串数组接收MD5的值
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    
    // 3.计算MD5值 最终字符串通过MD5加密的值 会被存储到result数组当中
    CC_MD5(strUTF, (CC_LONG)strlen(strUTF), result);
    
    // 4.定义一个字符串 通过拼接 接收MD5加密之后的值
    NSMutableString *MD5String = [NSMutableString string];
    
    // 5.通过循环 对MD5加密的值 进行逐个字符拼接到字符串中
    for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
    {
        [MD5String appendFormat:@"%02X", result[i]];
    }
    return MD5String;
}

#pragma mark --- 对复杂对象进行归档 ---
// 必须先将对象 转化成 data 然后对data进行MD5加密 返回复杂对象加密后的字符串
- (NSString *)MD5WithData:(NSData *)data
{
    // 1.创建MD5变量
    CC_MD5_CTX md5;
    // 2.对MD5变量进行初始化
    CC_MD5_Init(&md5);
    // 3.对MD5加密进行准备
    CC_MD5_Update(&md5, data.bytes, (CC_LONG)strlen(data.bytes));
    // 4.创建字符串数组 接收MD5值
    unsigned char result [CC_MD5_DIGEST_LENGTH];
    // 5.定义一个字符串 用于接收MD5值
    NSMutableString *MD5String = [NSMutableString string];
    // 6.通过循环 对MD5加密的值 进行逐个字符拼接到字符串
    for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
    {
        [MD5String appendFormat:@"%02X", result[i]];
    }
    return MD5String;
}
/*
#pragma mark --- 使用RSA 进行加密 ---
// 传入一个普通字符串 进行 RSA加密
- (NSString *)RSAEncrptyString:(NSString *)string
{
    NSString *publicKey = @"-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDEChqe80lJLTTkJD3X3Lyd7Fj+\nzuOhDZkjuLNPog3YR20e5JcrdqI9IFzNbACY/GQVhbnbvBqYgyql8DfPCGXpn0+X\nNSxELIUw9Vh32QuhGNr3/TBpechrVeVpFPLwyaYNEk1CawgHCeQqf5uaqiaoBDOT\nqeox88Lc1ld7MsfggQIDAQAB\n-----END PUBLIC KEY-----";
    NSString *RSAString = [RSA encryptString:string publicKey:publicKey];
    return RSAString;
}

#pragma mark --- 使用RSA 进行解密 ---
// 传入一个被RSA加密后结果的字符串 进行解密 ---
- (NSString *)RSADecryptString:(NSString *)string
{
    NSString *privateKey =  @"-----BEGIN RSA PRIVATE KEY-----\nMIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMQKGp7zSUktNOQk\nPdfcvJ3sWP7O46ENmSO4s0+iDdhHbR7klyt2oj0gXM1sAJj8ZBWFudu8GpiDKqXw\nN88IZemfT5c1LEQshTD1WHfZC6EY2vf9MGl5yGtV5WkU8vDJpg0STUJrCAcJ5Cp/\nm5qqJqgEM5Op6jHzwtzWV3syx+CBAgMBAAECgYEApSzqPzE3d3uqi+tpXB71oY5J\ncfB55PIjLPDrzFX7mlacP6JVKN7dVemVp9OvMTe/UE8LSXRVaFlkLsqXC07FJjhu\nwFXHPdnUf5sanLLdnzt3Mc8vMgUamGJl+er0wdzxM1kPTh0Tmq+DSlu5TlopAHd5\nIqF3DYiORIen3xIwp0ECQQDj6GFaXWzWAu5oUq6j1msTRV3mRZnx8Amxt1ssYM0+\nJLf6QYmpkGFqiQOhHkMgVUwRFqJC8A9EVR1eqabcBXbpAkEA3DQfLVr94vsIWL6+\nVrFcPJW9Xk28CNY6Xnvkin815o2Q0JUHIIIod1eVKCiYDUzZAYAsW0gefJ49sJ4Y\niRJN2QJAKuxeQX2s/NWKfz1rRNIiUnvTBoZ/SvCxcrYcxsvoe9bAi7KCMdxObJkn\nhNXFQLav39wKbV73ESCSqnx7P58L2QJABmhR2+0A5EDvvj1WpokkqPKmfv7+ELfD\nHQq33LvU4q+N3jPn8C85ZDedNHzx57kru1pyb/mKQZANNX10M1DgCQJBAMKn0lEx\nQH2GrkjeWgGVpPZkp0YC+ztNjaUMJmY5g0INUlDgqTWFNftxe8ROvt7JtUvlgtKC\nXdXQrKaEnpebeUQ=\n-----END RSA PRIVATE KEY-----";
    NSString *resultString = [RSA decryptString:string privateKey:privateKey];
    return resultString;
}
*/

/**********
 
 以下是归档反归档的操作方法
 
 **********/

#pragma mark --- 复杂对象（单一Model数据模型）的归档 ---
- (NSData *)archiverModel:(id)model modelKey:(NSString *)modelKey
{
    NSMutableData *data = [NSMutableData data];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
    [archiver encodeObject:model forKey:modelKey];
    [archiver finishEncoding];
    return data;
}

#pragma mark -- 复杂对象（单独Model）反归档 ---
// 传入归档model写入文件的路径 返回该model  要通过model对象 得到model归档时的key值
- (id)unArchiverModelWithFilePath:(NSString *)filePath modelKey:(NSString *)modelKey
{
    // 2.从路径中获取数据
    NSData *data = [NSData dataWithContentsOfFile:filePath];
    // 3.创建反归档对象
    NSKeyedUnarchiver *unArchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
    // 4.进行对model的反归档读取
    id model = [unArchiver decodeObjectForKey:modelKey];
    return model;
}

#pragma mark --- 复杂对象（数组装载model）归档
- (NSData *)archiverArray:(NSArray *)array arrayKey:(NSString *)arrayKey
{
    NSMutableData *data = [NSMutableData data];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
        [archiver encodeObject:array forKey:arrayKey];
    [archiver finishEncoding];
    return data;
}

#pragma mark --- 复杂对象 (数组装载model)反归档
- (NSArray *)unArchiverArrayWithFilePath:(NSString *)filePath arrayKey:(NSString *)arrayKey
{
    NSData *data = [NSData dataWithContentsOfFile:filePath];
    NSKeyedUnarchiver *unArchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
    NSArray *array = [unArchiver decodeObjectForKey:@"modelArray"];
    return array;
}







/**********
 
 以下是在沙盒中Documents/Caches路径下操作文件或文件夹管理的方法
 
 **********/

#pragma mark --- 创建/获取文件夹的方法 ---
// 传入文件夹的名称 返回整个路径 传入0 在documents文件下创建文件夹 传入1 在caches文件下创建文件夹
- (NSString *)creatOrGetFileWithFileName:(NSString *)fileName type:(NSInteger)type
{
    NSString *filePath;
    if (type == 0)
    {
         filePath = [[self documentsFilePath] stringByAppendingPathComponent:fileName];
    }
    else
    {
        filePath = [[self cachesFilePath] stringByAppendingPathComponent:fileName];
    }
    NSFileManager *manager = [NSFileManager defaultManager];
    if (![manager fileExistsAtPath:filePath])
    {
        [manager createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:nil];
    }
    return filePath;
}

#pragma mark --- 创建/获取文件的方法 ---
// 传入文档的名称 返回整个路径  传入0 在documents文件下创建文件 传入1 在caches文件下创建文件
- (NSString *)creatOrGetDocWithWithDocName:(NSString *)docName type:(NSInteger)type
{
    NSString *filePath;
    if (type == 0)
    {
        filePath = [[self documentsFilePath] stringByAppendingPathComponent:docName];
    }
    else
    {
        filePath = [[self cachesFilePath] stringByAppendingPathComponent:docName];
    }
    NSFileManager *manager = [NSFileManager defaultManager];
    if (![manager fileExistsAtPath:filePath])
    {
        [manager createFileAtPath:filePath contents:nil attributes:nil];
    }
    return filePath;
}



#pragma mark --- 获取Documents路径 ---
- (NSString *)documentsFilePath
{
    return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
}

#pragma mark --- 获取Library/Caches路径 ---
- (NSString *)cachesFilePath
{
    return [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];

}


@end
